package com.tbit.uqbike.client.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.tbit.common.config.OssDefaultConfig;
import com.tbit.uqbike.client.constant.AccountConfigExtConstant;
import com.tbit.uqbike.client.dao.core.*;
import com.tbit.uqbike.client.dao.log.MachineFaultLogDao;
import com.tbit.uqbike.client.exception.BaseException;
import com.tbit.uqbike.client.pojo.*;
import com.tbit.uqbike.client.pojo.newEntity.AccountConfigExt;
import com.tbit.uqbike.client.service.AccountService;
import com.tbit.uqbike.client.service.SuggestionService;
import com.tbit.uqbike.client.util.Assert;
import com.tbit.uqbike.client.util.DateTimeUtil;
import com.tbit.uqbike.client.util.aliyun.FileLoadUtils;
import com.tbit.uqbike.client.util.aliyun.OssFileUtils;
import com.tbit.uqbike.client.util.huawei.Constant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.*;

@Slf4j
@Service("suggestionService")
public class SuggestionServiceImpl implements SuggestionService {
    @Autowired
    private SuggestionDao suggestionDao;
    @Autowired
    private AccountService accountService;
    @Autowired
    private OssConfigDao ossConfigDao;
    @Autowired
    private OssDefaultConfig ossDefaultConfig;
    @Autowired
    private AccountConfigExtDao accountConfigExtDao;
    @Autowired
    private MachineFaultLogDao machineFaultLogDao;
    @Autowired
    private MachineDao machineDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private MachineFaultDao machineFaultDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insert(Suggestion suggestion, List<MultipartFile> list,Double lo,Double la) {
        if (list.size() > 0) {
            StringBuffer name = new StringBuffer();
            try {
                for (MultipartFile multipartFile : list) {
                    if (!FileLoadUtils.checkFileSize(multipartFile, 2, "M")) {
                        throw new BaseException("-4003", "图片过大");
                    }
                    InputStream inputStream = multipartFile.getInputStream();
                    /**阿里云配置*/
                    OssConfig ossConfig = new OssConfig(ossDefaultConfig.getEndpoint(),
                            ossDefaultConfig.getAccessKeyId(),
                            ossDefaultConfig.getAccessKeySecret(), "gx-sugg");
                    Account account = accountService.getByAdAccountId(suggestion.getAccountId());
                    /**查询是否存在配置信息*/
                    OssConfig ossConfigDB = ossConfigDao.getByAccountId(account.getParentId());
                    if (ossConfigDB != null) {
                        ossConfig = ossConfigDB;
                    }
                    //添加图片
                    String imageId = UUID.randomUUID().toString();
                    /**上传阿里云*/
                    String fileName = OssFileUtils
                            .uploadByAliYun(inputStream, ossConfig, imageId, multipartFile.getContentType(),
                                    OssFileUtils.IMAGE);
                    name.append(fileName).append(";");
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
            if (name.length() > 1) {
                name.delete(name.length() - 1, name.length());
            }
            suggestion.setUrl(name.toString());
        }
        suggestionDao.insert(suggestion);
        //订单结束后的意见反馈(存在车辆编号)，需要统计配置时间内相同问题的提交次数，和配置的次数进行比较，如果达到了配置的次数，就把意见反馈转换成故障上报
        this.checkSugNumAndToFaultRe(suggestion,lo,la);
    }

    @Override
    public List<Suggestion> getByUserId(Integer userId) {
        return suggestionDao.getByUserId(userId);
    }

    @Override
    public List<Suggestion> queryPage(Integer userId, Integer pageNO, Integer pageSize) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("userId", userId);
        params.put("page", (pageNO - 1) * pageSize);
        params.put("rowCount", pageSize);
        return suggestionDao.queryPage(params);
    }

    @Override
    public Integer queryCount(Integer userId) {
        return suggestionDao.queryCount(userId);
    }



    /**
     * @description: 订单结束后的意见反馈(存在车辆编号)，需要统计配置时间内相同问题的提交次数，和配置的次数进行比较，如果达到了配置的次数，就把意见反馈转换成故障上报
     * @author: mo.shanyong
     * @date: 2024/11/19 11:29
     * @param: suggestion
     * @param: 经度
     * @param: 维度
     */
    private void checkSugNumAndToFaultRe(Suggestion suggestion,Double lo,Double la){
        //车辆编号为空说明不是订单结束的意见反馈
        if (Objects.isNull(suggestion.getUserCode()))
            return;
        //获取配置
        List<AccountConfigExt> configList = accountConfigExtDao.
                selectByAccountIdAndKeys(suggestion.getAccountId(),new HashSet<>(AccountConfigExtConstant.USER_FEEDBACK_SET_KEYS));
        if(CollectionUtils.isEmpty(configList))
            return;
        //如果不存在用户意见反馈转成故障上报开关或开关关闭就直接返回
        AccountConfigExt switchConfigExt = configList.stream().filter(accountConfigExt -> {
            return Objects.equals(accountConfigExt.getParamKey(), AccountConfigExtConstant.USER_FEEDBACK_SWITCH)
                    && Objects.equals(accountConfigExt.getParamValue(), AccountConfigExtConstant.USER_FEEDBACK_SWITCH_OPEN);
        }).findFirst().orElse(null);
        if (Objects.isNull(switchConfigExt))
            return;
        //记录一条故障上报日志
        MachineFaultLog machineFaultLog = this.addMachineFaultLog(suggestion, lo, la);
        //时间段
        AccountConfigExt dayConfigExt = configList.stream().filter(accountConfigExt -> {
            return Objects.equals(accountConfigExt.getParamKey(), AccountConfigExtConstant.USER_FEEDBACK_DAY);
        }).findFirst().orElse(null);
        //次数
        AccountConfigExt countConfigExt = configList.stream().filter(accountConfigExt -> {
            return Objects.equals(accountConfigExt.getParamKey(), AccountConfigExtConstant.USER_FEEDBACK_COUNT);
        }).findFirst().orElse(null);
        if (Objects.isNull(dayConfigExt) || Objects.isNull(countConfigExt))
            return;
        //根据配置判断当前是否要把车辆转变为故障车辆
        this.checkTimeAndCount(dayConfigExt, countConfigExt, machineFaultLog);
    }
    /**
     * @description: 记录故障上报日志
     * @author: mo.shanyong
     * @date: 2024/11/19 17:33
     * @param: suggestion 意见反馈
     * @param: lo 经度
     * @param: la 维度
     */
    private MachineFaultLog addMachineFaultLog(Suggestion suggestion,Double lo,Double la){
        Machine machine = machineDao.getByUserCode(suggestion.getUserCode());
        Assert.notNull(machine,"-2001","车辆不存在");
        User user = userDao.getByUserId(suggestion.getUserId());
        user = Objects.isNull(user) ? new User() : user;
        //查询该车辆最新的一条故障上报记录
        MachineFaultLog newestMachineFaultLog = machineFaultLogDao.selectNewestLog(machine.getMachineId());
        String orderNO = IdUtil.objectId();
        if (newestMachineFaultLog != null && StringUtils.hasText(newestMachineFaultLog.getOrderNO())
                && !newestMachineFaultLog.getFaulttype().equals(4) && !newestMachineFaultLog.getFaulttype().equals(3)) {
            orderNO = newestMachineFaultLog.getOrderNO();
        }
        String nowTime = DateTimeUtil.getNowTime();
        MachineFaultLog machineFaultLog = new MachineFaultLog();
        machineFaultLog.setAccountId(suggestion.getAccountId())
                .setMachineId(machine.getMachineId())
                .setUserCode(machine.getUserCode())
                .setAddManid(suggestion.getUserId())
                .setAddManName(user.getName())
                .setAddManPhone(user.getPhone())
                .setAddTime(DateUtil.parse(nowTime, "yyyy-MM-dd HH:mm:ss"))
                .setFaults("短时骑行结束订单")
                .setIntoMain(3)
                .setPoint(lo + "," + la)
                .setFaulttype(5)
                .setMachineType(machine.getMachineType())
                .setRemark(suggestion.getContent().replace(suggestion.getUserCode(),""))
                .setOrderNO(orderNO);
        machineFaultLogDao.insert(machineFaultLog);
        return machineFaultLog;
    }

    /**
     * @description: 根据配置判断当前是否要把车辆转变为故障车辆
     * @author: mo.shanyong
     * @date: 2024/11/19 17:34
     * @param: dayConfigExt 天数配置
     * @param: countConfigExt 次数配置
     * @param: machineFaultLog 故障上报日志
     * @return: boolean
     */
    public boolean checkTimeAndCount(AccountConfigExt dayConfigExt,
                                     AccountConfigExt countConfigExt,
                                     MachineFaultLog machineFaultLog){
        //天数
        Integer dayTime = Integer.valueOf(dayConfigExt.getParamValue());
        //次数
        Integer limitNum = Integer.valueOf(countConfigExt.getParamValue());
        //满足条件且实时表没有则添加到实时表
        if (dayTime > 0) {
            Integer count = machineFaultLogDao.getCountByMaIdAndDayAndRekFts(machineFaultLog.getMachineId(),dayTime,machineFaultLog.getRemark(),machineFaultLog.getFaults());
            if (Objects.nonNull(count) && count >= limitNum) {
                MachineFault machineFaultInDb = machineFaultDao.getByMachineId(machineFaultLog.getMachineId());
                if (machineFaultInDb == null) {
                    Machine machine = machineDao.getByMachineId(machineFaultLog.getMachineId());
                    MachineFault machineFault = new MachineFault();
                    machineFault.setFaults(machineFaultLog.getFaults());
                    machineFault.setFrom(machineFaultLog.getIntoMain());
                    machineFault.setOrderNO(machineFaultLog.getOrderNO());
                    machineFault.setMachineNO(machine.getMachineNO());
                    machineFault.setMachineId(machine.getMachineId());
                    machineFault.setAddMan(machineFaultLog.getAddManName());
                    machineFault.setPoint(machineFaultLog.getPoint());
                    machineFault.setRemark(machineFaultLog.getRemark());
                    machineFault.setUpdateTime(DateTimeUtil.getNowTime());
                    machineFaultDao.insert(machineFault);
                }
                return true;
            }
        }
        return false;
    }

}  